#pragma once

#include "OscOutboundPacketStream.h"
#include "UdpSocket.h"
#include "IpEndpointName.h"
#include "TcpServer.h"
#include "SMT.h"
using namespace std;


#define MAX_BUF_SIZE 2048
#define MAX_FLOAT_SIZE 48

enum OSCFormat
{
	OSC_RAW,
	OSC_XML
};

struct CMTCMTDriveServerProps
{
	int iSize;
	DWORD dwIP;
	long lPort;
	OSCFormat oscFormat;
	bool bUDP;
	bool bSysMouse;
	bool bRelative;
	bool bFlipV;
	bool bFlipH;
	long lWidth;
	long lHeight;
};

// Simple critical section with locking
//
class CMTCritSec 
{
#if defined(DEBUG) || defined(_DEBUG)

public:
	// Construction
	//
	CMTCritSec();
	~CMTCritSec();

	// Locking
	//
	void Lock();
	void Unlock();

	// Trace functions
	//
	bool CritCheckIn(CMTCritSec * pcCrit);
	bool CritCheckOut(CMTCritSec * pcCrit);
	void DbgLockTrace(CMTCritSec * pcCrit, bool fTrace);

	DWORD   m_currentOwner;
	DWORD   m_lockCount;
	bool    m_fTrace;

#else DEBUG

public:
	CMTCritSec();
	~CMTCritSec();
	void Lock();
	void Unlock();	

#endif DEBUG

private:
	CMTCritSec(const CMTCritSec &refCritSec);
	CMTCritSec &operator=(const CMTCritSec &refCritSec);

	CRITICAL_SECTION m_CritSec;
};

class CMTAutoLock
{
	CMTAutoLock(const CMTAutoLock &refAutoLock);
	CMTAutoLock &operator=(const CMTAutoLock &refAutoLock);

public:
	CMTAutoLock(CMTCritSec *plock)
	{
		m_pLock = plock;
		m_pLock->Lock();
	};

	~CMTAutoLock()
	{
		m_pLock->Unlock();
	};

private:
	CMTCritSec *m_pLock;
};

class CMTDriveServer
{
public:
	CMTDriveServer(void);
	virtual ~CMTDriveServer(void);

	bool InitServer(const CMTCMTDriveServerProps &props, HWND hwnd, int iID);
	bool StartServer();
	bool StopServer();
	bool ShutDown();
	bool UpdateServer(const CMTCMTDriveServerProps &props);	

private:
	void FireSysMouseEvent(int iX,int iY);
	void PrintServerState(LPCTSTR strMsg);
	bool UpdateCursorOSC();
	bool UpdateCursorXML();
	static DWORD WINAPI UpdataSensor(void *pData);

	struct CMTCursor
	{
		int ID;
		float x;
		float y;
		float dx;
		float dy;
		float m;
	}m_cmtCursor;

	struct CMTCursorChar
	{
		char ccID[MAX_FLOAT_SIZE];
		char cX[MAX_FLOAT_SIZE];
		char cY[MAX_FLOAT_SIZE];
		char cDX[MAX_FLOAT_SIZE];
		char cDY[MAX_FLOAT_SIZE];
		char cM[MAX_FLOAT_SIZE];
	}m_cmtCursorChar;

	struct CMTSession
	{
		char cstrHost[128];
		unsigned long lPort;
		unsigned long lFseq;
		char cPort[MAX_FLOAT_SIZE];
		char cFseq[MAX_FLOAT_SIZE];
	}m_cmtSession;

	CMTCritSec m_cs;
	CMTCritSec m_csPrint;
	CMTCMTDriveServerProps m_props;
	TcpServer *m_TcpServer;
	UdpTransmitSocket *m_UdpServer;
	bool m_bRunThread;
	HANDLE  m_thread;
	char m_buffer[MAX_BUF_SIZE];
	osc::OutboundPacketStream *m_pOSCPacket;
	string m_strXML;
	SMT_SENSOR m_cmtSensor;
	std::vector<SMT_CURSOR> m_vCursors;
	HWND m_msgDrain;
	int m_iDlgItemID;

	POINT m_pointMouse;
	
};
